#include <vector>
#include <semaphore.h>
#include <pthread.h>
using namespace std;

//一个队列可以分为多个格子，但一个格子就不能再分了！
template<class T>
class RingQUeue
{
    static const int DefaultNum = 5;

public:

    //封装PV操作
    void P(sem_t* sem)
    {
        sem_wait(sem);
    }
    void V(sem_t* sem)
    {
        sem_post(sem);
    }

    //封装加锁操作
    void Lock(pthread_mutex_t* lock)
    {
        pthread_mutex_lock(lock);
    }
    void UnLock(pthread_mutex_t* lock)
    {
        pthread_mutex_unlock(lock);
    }

    void Push(const T& in)
    {
        P(&_space_sem);

        Lock(&_p_lock);
        _rq[_p_step] = in;
        _p_step++;
        _p_step % _rq.size();        
        UnLock(&_p_lock);

        V(&_data_sem);
    }

    T Pop()
    {
        P(&_data_sem);

        Lock(&_c_lock);
        T t = _rq[_c_step];
        _c_step++;
        _c_step % _rq.size();       
        UnLock(&_c_lock);

        V(&_space_sem);
        return t;
    }

    RingQUeue()
    :_rq(vector<T>(DefaultNum)),_p_step(0),_c_step(0)
    {
        sem_init(&_space_sem,0,DefaultNum);
        sem_init(&_data_sem,0,0);

        pthread_mutex_init(&_p_lock, nullptr);
        pthread_mutex_init(&_c_lock, nullptr);
    }

    ~RingQUeue()
    {
        sem_destroy(&_space_sem);
        sem_destroy(&_data_sem);

        pthread_mutex_destroy(&_p_lock);
        pthread_mutex_destroy(&_c_lock);
    }

private:
    vector<T> _rq;

    int _p_step;
    int _c_step;

    sem_t _space_sem;   //生产者看到的是空间资源
    sem_t _data_sem;    //消费者看到的是数据资源

    pthread_mutex_t _p_lock;    //生产者间的互斥关系
    pthread_mutex_t _c_lock;    //消费者间的互斥关系
};
